package com.tianji.learning.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.remark.RemarkClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.autoconfigure.mq.RabbitMqHelper;
import com.tianji.common.constants.MqConstants;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.ReplyDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.ReplyPageQuery;
import com.tianji.learning.domain.vo.ReplyVO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.mq.message.SignlnMessage;
import com.tianji.learning.service.IInteractionReplyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 互动问题的回答或评论 服务实现类
 *
 * @author
 */
@Service
@RequiredArgsConstructor
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply> implements IInteractionReplyService {
    private final InteractionReplyMapper replyMapper;
    private final InteractionQuestionServiceImpl questionService;
    private final UserClient userClient;
    private final RemarkClient remarkClient;
    private final RabbitMqHelper rabbitMqHelper;


    /**
     * 新增回答或评论
     *
     * @param replyDTO
     */
    @Override
    public void addAnswer(ReplyDTO replyDTO) {
        //提交评论或回答
        InteractionReply reply = BeanUtils.copyBean(replyDTO, InteractionReply.class);
        reply.setUserId(UserContext.getUser());
        reply.setCreateTime(LocalDateTime.now());
        reply.setUpdateTime(LocalDateTime.now());
        replyMapper.insert(reply);//写入回答或评论
        if (replyDTO.getAnswerId() != null) { /*如果它有上一级回答id就说明是评论*/
            //累加回答评论次数
            lambdaUpdate().eq(InteractionReply::getId, replyDTO.getAnswerId())
                    .setSql("reply_times = reply_times + 1")
                    .update();


        } else {
            //回答
            questionService.lambdaUpdate()
                    .eq(InteractionQuestion::getId, replyDTO.getQuestionId())
                    .setSql("answer_times = answer_times + 1")
                    .set(replyDTO.getIsStudent(),InteractionQuestion::getStatus, QuestionStatus.UN_CHECK)
                    .set(replyDTO.getAnswerId() == null,InteractionQuestion::getLatestAnswerId,reply.getId())
                    .update();
            }
        /*发送信息,增加积分*/
        rabbitMqHelper.send(
                MqConstants.Exchange.LEARNING_EXCHANGE,
                MqConstants.Key.WRITE_REPLY,
               SignlnMessage.of(UserContext.getUser(), 5));// 签到积分是基本得分+奖励积分
        }


    /**
     * 分页查询回答或评论列表
     *
     * @param query
     * @return
     */
    @Override
    public PageDTO<ReplyVO> pageSelect(ReplyPageQuery query) {

        //不能为空
        Long answerId = query.getAnswerId();/*回答id*/
        Long questionId = query.getQuestionId();/*问题id*/
        if (questionId == null && answerId == null) {
            throw new RuntimeException("问题id和回答id不能同时为空");
        }

        //分页查询
        Page<InteractionReply> page = lambdaQuery()
                .eq(ObjectUtils.isNotNull(answerId),InteractionReply::getAnswerId, query.getAnswerId())
                .eq(ObjectUtils.isNull(answerId),InteractionReply::getAnswerId, 0L)
                .eq(ObjectUtils.isNotNull(questionId),InteractionReply::getQuestionId, query.getQuestionId())
                .eq(InteractionReply::getHidden, false)
                .page(query.toMpPageDefaultSortByCreateTimeDesc());

        List<InteractionReply> records = page.getRecords();/*查看内容*/
        if (ObjectUtils.isEmpty(records)) {
            return PageDTO.empty(page);
        }

        //远程调用，通过id查详情
        Set<Long> userIds = records.stream().map(InteractionReply::getUserId).collect(Collectors.toSet());

        List<UserDTO> userInfo = userClient.queryUserByIds(userIds);/*获得用户详情*/
        //转为map
        Map<Long, UserDTO> userMap = userInfo.stream().collect(Collectors.toMap(UserDTO::getId, user -> user));
    /*==========调用远程，拿到所有已经点赞的集合=======================*/

        Set<Long> answerIds= new HashSet<>();/*拿到所有的回答和评论的id，从下面循环存进去的*/
        for (InteractionReply record : records) {
            answerIds.add(record.getId());/*存入所有的回答和评论的id*/
        }
        Set<Long> allLikedIds = remarkClient.isBizLiked(answerIds);/*拿到所有点赞的集合*/


        //封装vo
        List<ReplyVO> voList = new ArrayList<>(records.size());
        for (InteractionReply record : records) {

            //拷贝属性
            ReplyVO vo = BeanUtils.copyBean(record, ReplyVO.class);

            //判断不是匿名
            if (!record.getAnonymity()) {/*默认是不匿名，如果是匿名返回true*/
                UserDTO userDTO = userMap.get(record.getUserId());/*通过key找值*/
                if (userDTO != null) {
                    vo.setUserName(userDTO.getName());
                    vo.setUserIcon(userDTO.getIcon());
                }
                if (record.getTargetReplyId() != null) {
                    //有评论
                    UserDTO target = userClient.queryUserById(record.getTargetUserId());/*优化可以写两个map*/
                    if (target != null) {
                        vo.setTargetUserName(target.getUsername());
                    }
                }
            }
            /*查看这个id是否包含在所有点赞集合中，有就返回ture,就会显示已经点赞了*/
            vo.setLiked(allLikedIds.contains(record.getId()));

            //添加到集合中
            voList.add(vo);
        }


        return PageDTO.of(page, voList);
    }



    /**
     * 分页查询回答或评论列表
     *
     * @param query
     * @return
     */
    @Override
    public PageDTO<ReplyVO> adminPageQuery(ReplyPageQuery query) {
        // 1、参数校验：课程ID和小节ID不能同时为空
        Long questionId = query.getQuestionId();
        Long answerId = query.getAnswerId();
        long num=0;
        if (questionId == null && answerId == null) {
            throw new BadRequestException("问题ID和回答ID不能同时为空!");
        }
        // 2、分页查询
        Page<InteractionReply> pageResult = lambdaQuery()
                .eq(ObjectUtil.isNull(answerId), InteractionReply::getAnswerId, num)
                .eq(ObjectUtil.isNotNull(questionId), InteractionReply::getQuestionId, questionId)
                .eq(ObjectUtil.isNotNull(answerId), InteractionReply::getAnswerId, answerId)
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionReply> records = pageResult.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            return PageDTO.empty(pageResult);
        }
        // 3、补充信息查询，查询回答者信息（昵称，头像），查询被评论的用户昵称
        //3.1 收集回答者的id集合，回复目标用户的id集合
        Set<Long> userIds = new HashSet<>(records.size());
        for (InteractionReply record : records) {
            if (record.getUserId() != null) {
                userIds.add(record.getUserId());
            }
            if (record.getTargetUserId() != null) {
                userIds.add(record.getTargetUserId());
            }
        }
        //3.2 根据用户ID集合远程调用查询用户信息集合 -> 转成Map （用户ID： 用户信息对象）
        Map<Long, UserDTO> userMap = new HashMap<>();
        if (ObjectUtil.isNotEmpty(userIds)) {
            List<UserDTO> userInfoList = userClient.queryUserByIds(userIds);
            if (ObjectUtil.isNotEmpty(userInfoList)) {
                userMap = userInfoList.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));
            }
        }
        // 4、循环遍历分页数据，封装VO集合
        List<ReplyVO> voList = new ArrayList<>(records.size());
        for (InteractionReply record : records) {
            // 4.1、拷贝数据
            ReplyVO vo = BeanUtils.copyBean(record, ReplyVO.class);
            UserDTO userInfo = userMap.get(record.getUserId());
            UserDTO taegetUserInfo = userMap.get(record.getTargetUserId());
            if (userInfo != null) {
                vo.setUserName(userInfo.getName());
                vo.setUserIcon(userInfo.getIcon());
            }
            if (taegetUserInfo != null) {
                vo.setTargetUserName(taegetUserInfo.getName());
            }
            voList.add(vo);
        }
        return PageDTO.of(pageResult, voList);
    }

    /**
     * 修改回答或评论的隐藏状态
     *
     * @param id
     * @param hidden
     */
    @Override
    public void updateHiddenById(Long id, Boolean hidden) {
        InteractionReply reply = getById(id);
        lambdaUpdate().set(InteractionReply::getHidden, hidden)
                .eq(InteractionReply::getId, id).update();
        if (reply.getAnswerId() == 0) {
            lambdaUpdate().set(InteractionReply::getHidden, hidden)
                    .eq(InteractionReply::getAnswerId, id).update();
        }
    }
}
